function runMicroTask(callback) {
  // 判断node环境
  // 为了避免「变量未定义」的错误，这里最好加上前缀globalThis
  // globalThis是一个关键字，指代全局对象，浏览器环境为window，node环境为global
  if (globalThis.process && globalThis.process.nextTick) {
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    const p = document.createElement('p');
    const observer = new MutationObserver(callback);
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = '1';
  } else {
    setTimeout(callback, 0);
  }
}

function isPromise(obj) {
  return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
}

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class Promise {
  _value;
  _state;
  _handleList;
  constructor(fnc) {
    this._value = undefined;
    this._state = PENDING;
    this._handleList = [];
    try {
      fnc(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      this._reject(error);
    }
  }

  _reject(value) {
    this._value = value;
    this._changeState(REJECTED);
  }
  _resolve(value) {
    this._value = value;
    this._changeState(FULFILLED);
  }

  _changeState(state) {
    if (this._state != PENDING) {
      return;
    }
    this._state = state;

    _runHandlers();
  }

  _runHandlers() {
    if (this._state === PENDING) {
      return;
    }
    while (this._handleList[0]) {
      this._runOneHandler(this._handleList[0]);
      this._handleList.shift();
    }
  }

  _runOneHandler({ executor, state, resolve, reject }) {
    runMicroTask(() => {
      if (state != this._state) {
        return;
      }
      if (typeof executor != 'function') {
        state === FULFILLED ? resolve(this._value) : reject(this._value);
      }
      try {
        const result = executor(this._value);
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (error) {
        reject(this._value);
      }
    });
  }

  _pushHandler(executor, state, resolve, reject) {
    this._handleList.push({
      executor,
      state,
      resolve,
      reject,
    });
  }

  then(onFulFilled, onRejected) {
    return new Promise((resolve, reject) => {
      this._pushHandler(onFulFilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers();
    });
  }

  catch(fn) {
    return this.then(null, fn);
  }

  finally(fn) {
    return this.then(fn);
  }
}

Promise.reject = function (value) {
  if (value instanceof Promise) {
    return value;
  }
  return new Promise((resolve, reject) => {
    if (isPromise(value)) {
      value.then(resolve, reject);
    } else {
      resolve(value);
    }
  });
};

Promise.reject = function (value) {
  return new Promise((resolve, reject) => {
    reject(value);
  });
};

Promise.all = function (arr) {
  let count = 0;
  const results = [];
  return new Promise((resolve, reject) => {
    try {
      arr.forEach((element, i) => {
        Promise.resolve(element).then((data) => {
          count++;
          results[i] = data;
          if (count === arr.length) {
            resolve(results);
          }
        }, reject);
      });
    } catch (error) {
      reject(error);
    }
  });
};

Promise.allSettled = function (arr) {
  const ps = [];
  for (p of arr) {
    ps.push(
      Promise.resolve(p).then(
        (value) => {
          return {
            value,
          };
        },
        (value) => {
          return {
            value,
          };
        }
      )
    );
  }
  return Promise.all(ps);
};

Promise.race = function (arr) {
  return new Promise((resolve, reject) => {
    for (p of arr) {
      Promise.resolve(p).then(resolve, reject);
    }
  });
};
